/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_HTBL_
#define	_INC_AK_HTBL_

#include "ak_types.h"
#include "ak_lru.h"
#include "ak_task.h"

#ifdef __cplusplus
extern "C" {
#endif


/* =====================================================================
**	Hash Bucket & Table
**	Operations: Get, Set, Add, Del.
**	
*/
#define _rHTBL_BUCKET_MAX  		64
#define _rHTBL_BUCKET_GC		8
#define _rHTBL_TICK_LAZY 		(_rHTBL_BUCKET_GC + 2)
static 	__inline  int	_SHTbl_KeyGen(void * pKey, int count, int entry)
{
	int i;
	unsigned char * 	pByte;
	unsigned int		b32;

	b32   = 0;
	pByte = (unsigned char *)pKey;
	FAST_EX8_OP(i, count, (b32 += *pByte, pByte++));
		
	return b32%entry;
}

struct _t_hTblLru;

typedef struct _t_hTblGc{
	_t_sysSemB				gcWake;
	struct _t_hTblLru * 	pHashTbl;
	
	_t_sysTask				thread;
	_t_sysTaskAttr 			tAttr;
}_t_hTblGc;

typedef struct _t_hTblLru{
	/* 
	**	Timer Tick, Add by a Trigger of 10 ms Period.  
	**	Which will then Trigger the GC. 
	**	1. Overflow. Need Check if == -1. 
	**	2. Judge. Use the Range() to check the Order. (Less, Equal, Great).
	*/
	time_t				current;		/* Just Start from 0 */
	
	_t_sysKLMem			klMem;
	_t_sysKLFunc		klFunc;
	
	_t_hTblGc			hTblGC;
	/* Key-Value Hash */
	_t_sysLruCt 		buckets[_rHTBL_BUCKET_MAX];
	
#if 0	
	/* Tags */
	_t_sys_LockRW		tagsLock;		/* Protects The Tags Tree as a whole */
	_t_rbroot			tagsRoot;
#endif
	
	/* Statistic */
	unsigned long		opsWr;
	unsigned long		opsRd;
	unsigned long		opsHit;
	unsigned long		opsMiss;
}_t_hTblLru;

extern	int 	SHTblLru_Init(_t_hTblLru * pHashTbl, _t_sysKLMem * pKLMem, _t_sysKLFunc * pKLFunc);



/* =====================================================================
**	Add the Support to Si-Looking Table
*/
#define _sHTBL_BUCKET_MAX  	256

typedef struct{
	/* Key-Value RB-Tree Node */
	_t_rbnode		upNode;	
	_t_rbnode		dnNode;	
	int 			state;
}_t_hTblSi_Ci;

typedef struct {
	_t_sysLockRW		lock;
	int 				index;
	int 				reserv;

	/* The RB-Tree of all Key-Value Pairs */
	_t_rbroot 			sTree;	
}_t_hTblSi_Ent;

#define _SIENT_INIT(pEnt, idx) 	\
	do{\
		SYS_LOCK_RW_INIT(&((pEnt)->lock));\
		RB_CLEAR_ROOT(&((pEnt)->sTree));\
		(pEnt)->index	= idx;	\
		(pEnt)->reserv 	= 0;	\
	}while(0)

typedef struct {
	_t_sysKLFunc 		klFunc;		/* Hash & Compare */
	/* Key-Value Hash */
	_t_hTblSi_Ent 		buckets[_sHTBL_BUCKET_MAX];
	
	/* Statistic */
	unsigned long		opsWr;
	unsigned long		opsRd;
	unsigned long		opsHit;
	unsigned long		opsMiss;
}_t_hTblSiS;

extern	int 			SHTblSis_Init(_t_hTblSiS * pSiTbl, _t_sysKLFunc * pHC);
extern	_t_rbnode *  	SHTblSis_Add(_t_hTblSiS * pSiTbl, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblSis_Find(_t_hTblSiS * pSiTbl, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblSis_Del(_t_hTblSiS * pSiTbl, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblSis_DelEx(_t_hTblSiS * pSiTbl, _t_rbnode * pNode, unsigned int iBucket);


/* =====================================================================
**	Add the Support to Bi-Looking Table
*/
#define _bHTBL_UP 			0
#define _bHTBL_DN 			1

#define _bHTBL_BUCKET_MAX  	256

typedef struct{
	/* Key-Value RB-Tree Node */
	_t_rbnode		upNode;	
	_t_rbnode		dnNode;	
	int 			state;
}_t_hTblBi_Ci;

typedef struct {
	_t_sysLockRW		lock;
	int 				index;
	int 				reserv;

	/* The RB-Tree of all Key-Value Pairs */
	_t_rbroot 			uTree;	
	_t_rbroot 			dTree;	

}_t_hTblBi_Ent;

#define _BIENT_INIT(pEnt, idx) 	\
	do{\
		SYS_LOCK_RW_INIT(&((pEnt)->lock));\
		RB_CLEAR_ROOT(&((pEnt)->uTree));\
		RB_CLEAR_ROOT(&((pEnt)->dTree));\
		(pEnt)->index	= idx;	\
		(pEnt)->reserv 	= 0;	\
	}while(0)

typedef struct {
	/* Key-Value Hash */
	_t_hTblBi_Ent 		buckets[_bHTBL_BUCKET_MAX];

	_t_sysKLFunc 			uHC;		/* Hash & Compare */
	_t_sysKLFunc 			dHC;		/* Hash & Compare */
	
	/* Statistic */
	unsigned long		opsWr;
	unsigned long		opsRd;
	unsigned long		opsHit;
	unsigned long		opsMiss;
}_t_hTblBiS;

extern	int 	SHTblBis_Init(_t_hTblBiS * pBiTbl, _t_sysKLFunc * pHC_Up, _t_sysKLFunc * pHC_Dn);
extern	_t_rbnode * 	SHTblBis_Add(_t_hTblBiS * pBiTbl, int type, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblBis_Find(_t_hTblBiS * pBiTbl, int type, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblBis_Del(_t_hTblBiS * pBiTbl, int type, _t_rbnode * pNode, unsigned int iBucket);
extern	_t_rbnode * 	SHTblBis_DelEx(_t_hTblBiS * pBiTbl, int type, _t_rbnode * pNode, unsigned int iBucket);



/* =====================================================================
**	Add the Support to 2-Level Looking Table.
**   1. Pri ----- > Sub 
**	2. Sub --->
**  	3. Key of -1 is Reserved.
*/

#define _lHTBL_BUCKET_MAX  	997
#define _lHTBL_KEY_GEN(vKey) 	((vKey)% _lHTBL_BUCKET_MAX)

typedef struct{
	_t_sysLockRW		lock;
	int 				index;
	int 				reserv;

	_t_blist 			eQue;
}_t_hTblLv_Ent;

typedef struct{
	_t_bnode 			node;
	_t_blist 			sQue;
	/* Reflector */
	_t_hTblLv_Ent 	* 	pEnt;
	
	int 				key;
	int 				type;
	int 				reserv;
}_t_hTblLv_Hdl;


typedef struct{
	_t_hTblLv_Ent 		buckets[_lHTBL_BUCKET_MAX];

	/* Sub Node Pool */
	_t_sysMHeap 		mHeap;
	_t_sysMPool 		mPool;

	/* Slots:  */
	_t_sysMSlot 		mSlot;
	
}_t_hTblLvS;

#define _SLENT_INIT(pEnt, idx) 	\
	do{\
		SYS_LOCK_RW_INIT(&((pEnt)->lock));\
		BLIST_INIT(&((pEnt)->eQue));\
		(pEnt)->index	= idx;	\
		(pEnt)->reserv 	= 0;	\
	}while(0)


extern	int 			SHTblLv_Init(_t_hTblLvS * phTblLvS, size_t mLimit);

/* The Level Handle Pool */
extern	int 			SHTblLv_PoolFree(_t_hTblLvS * phTblLvS, _t_hTblLv_Hdl * pHdl);
extern	_t_hTblLv_Hdl * SHTblLv_PoolAlloc(_t_hTblLvS * phTblLvS);

/* The Level Handle OPs */
extern	int 	SHTblLv_TblAdd(_t_hTblLvS * phTblLvS, int * sKey, int nKey, _t_bnode * pNode);
extern	int 	SHTblLv_TblDel(_t_hTblLvS * phTblLvS, int * sKey, int nKey, _t_bnode * pNode);

/* The Level Handle OPs */
extern	_t_hTblLv_Hdl *	SHTblLv_TblFind(_t_hTblLvS * phTblLvS, int * sKey, int nKey);
extern	_t_hTblLv_Hdl *	SHTblLv_TblSub( _t_hTblLv_Hdl * pHdl, int  idx);
extern	int				SHTblLv_TblCursor( _t_hTblLv_Hdl * pHdl,  int  offset,  int num, void ** ppNode);



/* =====================================================================
**	Add the Support to Casting Table.
**  	1. Key of -1 is Reserved.
*/

#define _cHTBL_BUCKET_MAX  		256
#define _cHTBL_KEY_GEN(vKey) 	((vKey)% _cHTBL_BUCKET_MAX)

typedef struct{
	_t_sysLockRW		lock;
	int 				index;
	int 				reserv;

	_t_blist 			eQue;
}_t_hTblCa_Ent;


typedef struct{
	_t_hTblCa_Ent 		buckets[_cHTBL_BUCKET_MAX];

	/* Statistic */
	unsigned long		opsWr;
	unsigned long		opsRd;
}_t_hTblCaS;

#define _CAENT_INIT(pEnt, idx) 	\
	do{\
		SYS_LOCK_RW_INIT(&((pEnt)->lock));\
		BLIST_INIT(&((pEnt)->eQue)); \
		(pEnt)->index	= idx;	\
		(pEnt)->reserv 	= 0;	\
	}while(0)


extern	int 			SHTblCa_Init(_t_hTblCaS * phTblCaS);

/* The Level Handle OPs */
extern	int 	SHTblCa_TblAdd(_t_hTblCaS * phTblCaS, int * sKey, int nKey, _t_bnode * pNode);
extern	int 	SHTblCa_TblDel(_t_hTblCaS * phTblCaS, int * sKey, int nKey, _t_bnode * pNode);



#ifdef __cplusplus
}
#endif

#endif


